package org.top10.dealor;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.top10.entity.Tag;


public class TagDealor {
	  private final static char beginTag='<';
	  private final static char endTag='>';
	  private CharStream charReader;
	  public TagDealor(CharStream charR){
		  charReader=charR;
	  }
	  public TagDealor(Reader r){
		  charReader=new FastCharStream(r);
	  }
	  public TagDealor(Reader r,int bufSIZE){
		  //charReader=new FastCharStream(r,bufSIZE);
	  }
	  private  boolean isBeginChar(char c){
		  if(c==beginTag)
			  return true;
		  return false;
	  }
	  private  boolean isEndChar(char c){
		  if(c==endTag)
			  return true;
		  return false;
	  }
	  private  boolean isEmptyChar(char c){
		  if(c==' '||c=='\r'||c=='\n'||c=='\t')
			  return true;
		  else
			  return false;
	  }
	  public  String getTagTextByTagName(String text,String tagName){
		//  List<Integer>pos=findTagPos(text,tagName,0);
		  return "";
	  }
	  public String getString(String text,String tagName,int index) throws IOException{
		  Tag btag=null;
		  int count=0;
		  int overCount=0;
		  int btagPos=0;
		  while(count<index){
			  btag= this.findTag(text, tagName,btagPos);
			 if(btag==null)return null;
			 btagPos=btag.getEndPos();
			 if(btag.isEndTag())continue;
			 count++;
		  }
		  Tag etag=null;
		  while(true){
			  etag=this.findTag(text, tagName,btagPos);
			  if(etag==null)return null;
			  btagPos=etag.getEndPos();
			  if(!etag.isEndTag()){
				  overCount++;
			  }
			  if(etag.isEndTag()&&overCount==0){
				 return text.substring(btag.getEndPos(),etag.getBeginPos());
			  }else{
				  overCount--;
			  }
		  }
	  }
	  
	  public  LinkedList<Tag> findTags(String text,String tagName,int beginPos){
		  LinkedList<Tag>tagPos=new LinkedList<Tag>();
		  int begin=beginPos;
		  Tag tag=null;
		  while(true){
			  tag=findTag(text,tagName,begin);
			  if(tag==null)
				  break;
			  else {
				  tagPos.add(tag);
				  begin=tag.getEndPos();
			  }
		  }
		  return tagPos;
	  }
	  public List<Tag> findBeginTags(String text,String tagName){
		  List<Tag> tags=findTags( text, tagName,0);
		  for(int t=tags.size()-1;t>=0;t--){
			  if(tags.get(t).isEndTag())tags.remove(t);
		  }
		  return tags;
	  }
	 public String getTextBetweenTags(Tag beginTag,Tag endTag){
		 if(endTag.getBeginPos()<=beginTag.getEndPos())return null;
		 return charReader.getString(beginTag.getEndPos(), endTag.getBeginPos());
	 }
	 public String getTextBetweenTags(Tag beginTag,Tag endTag,String text){
		 if(endTag.getBeginPos()<=beginTag.getEndPos())return null;
		 return text.substring(beginTag.getEndPos(), endTag.getBeginPos());
	 }
	
	  private  Tag findTag(String tagName,int beginPos) throws IOException{
		  int chartCount=beginPos;
		  int taglen=tagName.length();
		  boolean isBegin=false;
		  boolean isBeginSign=false;
		  boolean isEndTag=false;
		  boolean isEndSign=false;
		  int beginTag=-1;
		  int pos=0;
		  while(true){
			  char c=charReader.readChar(chartCount++);
			  if(isBeginChar(c)){
				  isBegin=true;
				  beginTag=chartCount-1;
				  pos=0;
				  isEndTag=false;
				  isBeginSign=false;
				  continue;
			  }
			  if(isBegin){
				  if(!isBeginSign){
					  if(c=='/'){
						  isEndTag=true;
						  continue;
					  }else if(!isEmptyChar(c)){
						  isBeginSign=true;
					  }else{
						continue;  
					  }
				  }
				  
				  if(pos<taglen&&c==tagName.charAt(pos)){
					  pos++;
					  continue;
				  }else if(pos<taglen){
					  pos=0;
					  isBeginSign=false;
					  isEndTag=false;
					  isBegin=false;
					  beginTag=-1;
					  continue;
				  }
				  if(!isEndSign&&pos==taglen){
					  if(isEmptyChar(c))
						  isEndSign=true;
					  else if(isEndChar(c))
						  return Tag.buildTag(tagName, beginTag,chartCount+1,isEndTag,charReader.getString(beginTag, chartCount+1));
					  else{
						  pos=0;
						  isBeginSign=false;
						  isEndTag=false;
						  isBegin=false;
						  beginTag=-1;
					  }
				  }
				  if(isEndSign&&isEndChar(c)){
					  //insert a tag
					 return Tag.buildTag(tagName, beginTag,chartCount+1,isEndTag,charReader.getString(beginTag, chartCount+1));
				  }
		  }
		  }
	  }
	  public  Tag findTag(String text,String tagName,int beginPos){
		  int tlen=text.length();
		  int taglen=tagName.length();
		  char c=' ';
		  int pos=0;
		  boolean isBegin=false;
		  boolean isBeginSign=false;
		  boolean isEndTag=false;
		  boolean isEndSign=false;
		  int beginTag=-1;
		  if(beginPos>=tlen||taglen+2>tlen)return null;
		  for(int t=beginPos;t<tlen;t++){
			  c=text.charAt(t);
			  if(isBeginChar(c)){
				  isBegin=true;
				  beginTag=t;
				  pos=0;
				  isEndTag=false;
				  isBeginSign=false;
				  continue;
			  }
			  if(isBegin){
				  if(!isBeginSign){
					  if(c=='/'){
						  isEndTag=true;
						  continue;
					  }else if(!isEmptyChar(c)){
						  isBeginSign=true;
					  }else{
						continue;  
					  }
				  }
				  
				  if(pos<taglen&&c==tagName.charAt(pos)){
					  pos++;
					  continue;
				  }else if(pos<taglen){
					  pos=0;
					  isBeginSign=false;
					  isEndTag=false;
					  isBegin=false;
					  beginTag=-1;
					  continue;
				  }
				  if(!isEndSign&&pos==taglen){
					  if(isEmptyChar(c))
						  isEndSign=true;
					  else if(isEndChar(c))
						  return Tag.buildTag(tagName, beginTag, t+1,isEndTag,text.substring(beginTag, t+1));
					  else{
						  pos=0;
						  isBeginSign=false;
						  isEndTag=false;
						  isBegin=false;
						  beginTag=-1;
					  }
				  }
				  if(isEndSign&&isEndChar(c)){
					  //insert a tag
					 return Tag.buildTag(tagName, beginTag, t+1,isEndTag,text.substring(beginTag, t+1));
				  }
			  }
		  }
		  return null;
	  }
	  public String getTagTextByName(String text,String tagName,int index) throws Exception{
		  Tag tag=findFirstBeginTag(text,tagName);
		  if(tag==null)return null;
		  Tag beginTag=null;
		  LinkedList <Tag>stack=new LinkedList<Tag>();
		  stack.push(tag);
		  int tagCount=0;
		  while(true){
			  tag=findTagWay(text,tagName,tag.getEndPos());
			  if(tag==null)return null;
			  if(tag.isEndTag()){
				  beginTag= stack.pop();
				  if(beginTag.getIndex()==index){
					  if(text!=null){
						return text.substring(beginTag.getEndPos()+1, tag.getBeginPos());  
					  }
					  return  charReader.getString(beginTag.getEndPos()+1, tag.getBeginPos());
				  }
				  
			  }else{
				  tagCount++;
				  tag.setIndex(tagCount);
				  stack.push(tag);
			  }
		   } 
	  }
	  public String getTagTextByName(String tagName,int index) throws Exception{
		 return getTagTextByName(null,tagName, index);
	  }
	  public Tag findFirstBeginTag(String tagName) throws IOException{
		  return findFirstBeginTag(null,tagName);
	  }
	 
	  public Tag findFirstBeginTag(String text,String tagName) throws IOException{
		  Tag beginTag=null;
		  beginTag=findTagWay(text,tagName,0);
		  while(beginTag!=null&&beginTag.isEndTag()){
			  beginTag=findTagWay(text,tagName,beginTag.getEndPos());
		  }
		  return beginTag;
	  } 
	  private Tag findTagWay(String text,String tagName,int pos) throws IOException{
		  Tag tag=null;
		  if(text!=null){
			  tag=findTag(text,tagName,pos);
		  }else{
			  tag=findTag(tagName,pos);
		  }
		  return tag;
	  }
	  
	  public  String getTagTextByName(String tagName,String sign) throws Exception{
		  Tag tag=findFirstBeginTag(tagName);
		  if(tag==null)return null;
		  Tag beginTag=null;
		  LinkedList <Tag>stack=new LinkedList<Tag>();
		  stack.push(tag);
		  Pattern p=Pattern.compile(sign,Pattern.MULTILINE);
		  while(true){
			  //System.out.println(tag.toString());
			  //System.out.println(charReader.getString(tag.getBeginPos(), tag.getEndPos()+1));
			  tag=findTag(tagName,tag.getEndPos());
			  if(tag==null)return null;
			  if(tag.isEndTag()){
				  beginTag=stack.poll();
				  String v=charReader.getString(beginTag.getBeginPos()+1, tag.getEndPos());
				 // System.out.println(v);
				  if(p.matcher(v).find())return v;
			  }else{
				  stack.push(tag);
			  }
		  }
	  }

	public static void main(String args[]){
		String s="<div>test2</div >";
		Pattern  p=Pattern.compile("test2");
		Matcher m=p.matcher(s);
		if(m.find())
			System.out.println(m.group());
		System.out.println(s.matches(".*test2.*"));
		InputStream is = FileDealor.class.getClassLoader().getResourceAsStream(
				"text.txt");
		InputStreamReader ff;
		try {
			ff = new InputStreamReader(is, "UTF-8");
			BufferedReader fr = new BufferedReader(ff);
			TagDealor d=new TagDealor(fr);
			String vv=d.getTagTextByName("div",".*test2.*");
			System.out.println(vv);
			System.out.println(d.getTagTextByName(vv,"div",1));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
}
